#pragma once

#include <iostream>
#include <string>
#include <vector>

namespace composite {

/// @brief 抽象构件, 为树叶构件和树枝构件声明公共接口，并实现它们的默认行为
///        - 透明式: 声明访问和管理子类的接口
///        - 安全式: 不声明访问和管理子类的接口，管理工作由树枝构件完成
class AbstractSafeComponent {
public:
    virtual ~AbstractSafeComponent() {}

    virtual void Operation() = 0;
};

/// @brief 树叶构件, 组合中的叶节点对象，它没有子节点，用于实现抽象构件角色中声明的公共接口
class LeafSafeComponent : public AbstractSafeComponent {
public:
    LeafSafeComponent(const std::string& name) : name_(name) {}

    // 树叶构件切实需要实现的接口
    virtual void Operation() {
        printf("this(%s) is LeafSafeComponent::Operation!\n", name_.c_str());
    }

private:
    std::string name_;
};

/// @brief 树枝构件, 组合中的分支节点对象，它有子节点。它实现了抽象构件角色中声明的接口，主要作用是存储和管理子部件
class CompositeSafeComponent : public AbstractSafeComponent {
public:
    // 安全式下, 由树枝构件自己实现对树叶构件的管理
    virtual void Add(AbstractSafeComponent* comp) {
        children_.emplace_back(comp);
    }
    virtual void Remove(AbstractSafeComponent* comp) {
        for (auto it = children_.begin(); it != children_.end(); it++) {
            if (comp == (*it)) {
                children_.erase(it++);
                break;
            }
        }
    }
    virtual AbstractSafeComponent* GetChild(const int id) {
        if (id >= 0 && id < children_.size()) return children_[id];
        return nullptr;
    }
    virtual void Operation() {
        for (auto* child : children_) {
            child->Operation();
        }
    }

private:
    std::vector<AbstractSafeComponent*> children_;
};

} // namespace composite

void Test_12_composite_impl_2() {
    printf("-------------------- %s --------------------\n", __FUNCTION__);
    composite::AbstractSafeComponent* composite_ptr = new composite::CompositeSafeComponent();
    
    composite::AbstractSafeComponent* leaf_ptr_A = new composite::LeafSafeComponent("leaf A");
    composite::AbstractSafeComponent* leaf_ptr_B = new composite::LeafSafeComponent("leaf B");
    composite::AbstractSafeComponent* leaf_ptr_C = new composite::LeafSafeComponent("leaf C");

    // 对树叶构件的操作
    {
        composite::CompositeSafeComponent* composite_son_ptr = dynamic_cast<composite::CompositeSafeComponent*>(composite_ptr);

        composite_son_ptr->Add(leaf_ptr_A);
        composite_son_ptr->Add(leaf_ptr_B);
        composite_son_ptr->Add(leaf_ptr_C);

        composite::AbstractSafeComponent* tmp_ptr = composite_son_ptr->GetChild(1);
        tmp_ptr->Operation();
        composite_son_ptr->Remove(leaf_ptr_B);
    }

    composite_ptr->Operation();

    delete composite_ptr;
    delete leaf_ptr_A;
    delete leaf_ptr_B;
    delete leaf_ptr_C;
}

// -------------------- Test_12_composite_impl_2 --------------------
// this(leaf B) is LeafSafeComponent::Operation!
// this(leaf A) is LeafSafeComponent::Operation!
// this(leaf C) is LeafSafeComponent::Operation!